﻿using System;

namespace Oxage.Midi
{
	public class MidiMessage : IMessage
	{
		#region Constructor
		public MidiMessage()
		{
		}
		#endregion

		#region Properties
		public MidiEvents Event
		{
			get;
			set;
		}

		public byte Channel
		{
			get;
			set;
		}

		public byte Note
		{
			get;
			set;
		}

		public byte Velocity
		{
			get;
			set;
		}
		#endregion

		#region Methods
		public byte[] Encode()
		{
			switch (this.Event)
			{
				case MidiEvents.NoteOn:
					return new byte[] { (byte)(0x90 | this.Channel), this.Note, this.Velocity  };

				case MidiEvents.NoteOff:
					return new byte[] { (byte)(0x80 | this.Channel), this.Note, this.Velocity };

				case MidiEvents.ProgramChange:
					return new byte[] { (byte)(0xC0 | this.Channel), this.Note, this.Velocity };

				case MidiEvents.Aftertouch:
					return new byte[] { (byte)(0xA0 | this.Channel), this.Note, this.Velocity };

				default:
					return new byte[0];
			}
		}

		public void Decode(byte[] bytes)
		{
			this.Event = MidiEvents.Unknown;
			if (bytes != null && bytes.Length == 3)
			{
				if ((bytes[0] & 0x90) == 0x90)
				{
					this.Event = MidiEvents.NoteOn;
					this.Channel = (byte)(bytes[0] & ~0x90);
				}
				else if ((bytes[0] & 0x80) == 0x80)
				{
					this.Event = MidiEvents.NoteOff;
					this.Channel = (byte)(bytes[0] & ~0x90);
				}
				else if ((bytes[0] & 0xC0) == 0xC0)
				{
					this.Event = MidiEvents.ProgramChange;
					this.Channel = (byte)(bytes[0] & ~0xC0);
				}
				else if ((bytes[0] & 0xA0) == 0xA0)
				{
					this.Event = MidiEvents.Aftertouch;
					this.Channel = (byte)(bytes[0] & ~0xA0);
				}

				this.Note = bytes[1];
				this.Velocity = bytes[2];
			}
		}
		#endregion
	}
}
